using System;
using System.Collections.Generic;
using Game500.ClientServerCommon.Src;

namespace Game500.Client.Src.Networking
{
  public abstract class ClientNetworkManager
  {
    #region Delegates

    public delegate void ExplosionDelegate(ExplosionsEvent ev);

    public delegate void GameStartDelegate();

    public delegate void PlayerLimitReachedDelegate(PlayerLimitReachedEvent ev);

    public delegate void ShotDelegate(ShotsEvent ev);

    #endregion

    protected readonly Dictionary<GamerActionType, GamerAction> Actions = new Dictionary<GamerActionType, GamerAction>();

    public abstract GameInfo GameInfo { get; }

    public abstract void Connect(string host, int port);

    public abstract SceneFrame GetActualFrame();

    public event GameStartDelegate GameStartedEvent;
    public event ShotDelegate ShotsEvent;
    public event ExplosionDelegate ExplosionsEvent;
    public event PlayerLimitReachedDelegate PlayerLimitReachedEvent;

    public static ClientNetworkManager Create(string name)
    {
      //if (name == "fake") return new FakeClientNetworkManager();
      if (name == "tcp") return new TcpClientNetworkManager();
      throw new Exception(string.Format("Can not create objects of type '{0}'. Program will now exit", name));
    }

    protected void RaiseGameStartEvent()
    {
      if (GameStartedEvent != null)
      {
        GameStartedEvent();
      }
    }

    protected void RaiseShotsEvent(ShotsEvent ev)
    {
      if (ShotsEvent != null)
      {
        ShotsEvent(ev);
      }
    }

    protected void RaiseExplosionsEvent(ExplosionsEvent ev)
    {
      if (ExplosionsEvent != null)
      {
        ExplosionsEvent(ev);
      }
    }

    protected void RaisePlayerLimitReachedEvent(PlayerLimitReachedEvent ev)
    {
      if (PlayerLimitReachedEvent != null)
      {
        PlayerLimitReachedEvent(ev);
      }
    }

    public abstract void Initialize();

    public abstract void Update();

    public void AddAction(GamerAction action)
    {
      GamerAction result;
      if (Actions.TryGetValue(action.Type, out result))
      {
        result.Value += action.Value;
      }
      else
      {
        Actions[action.Type] = action;
      }
    }

    public abstract void SendGamerInfo(GamerInfo gamerInfo);
  }
}